package top.songxs.gmall.gateway.filter;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import top.songxs.gmall.common.constant.GmallCacheConstant;
import top.songxs.gmall.gateway.properties.AuthResourceProperties;
import top.songxs.gmall.user.entity.UserInfo;

import java.util.List;

@Component
@Slf4j
public class UserAuthFilter implements GlobalFilter, Ordered {

    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    private AuthResourceProperties authResourceProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        log.info("走了全局过滤器！！！！{}", path);
        //如果请求路径满足静态资源路径直接放行
        List<String> staticPath = authResourceProperties.getStaticPath();//静态资源的路径
        for (String pathPattern : staticPath) {
            //满足直接放行
            if (antPathMatcher.match(pathPattern, path)) {
                return chain.filter(exchange);
            }
        }

        List<String> authUrl = authResourceProperties.getAuthUrl();
        for (String authUrlPattern : authUrl) {
            //满足条件就要验证
            if (antPathMatcher.match(authUrlPattern, path)) { // 符合当前路径规则，那么此时就需要验证用户登录
                // token的值为空，直接跳转到登录页面
                String token = this.getUserToken(exchange);
                if (StringUtils.isEmpty(token)) {
                    return locationUrl(exchange, authResourceProperties.getMainUrl());
                } else {
                    // 从Redis中根据token获取用户数据,如果拿到的数据为空则token是伪造的直接返回到主页
                    UserInfo userInfo = this.getUserInfoByToken(token);
                    if (userInfo == null) {
                        return locationUrl(exchange, authResourceProperties.getMainUrl());
                    } else {
                        return this.userIdThrough(exchange, chain, userInfo);
                    }
                }
            }
        }

        //普通请求
        String userToken = this.getUserToken(exchange);
        if (!StringUtils.isEmpty(userToken)) {
            UserInfo userInfoByToken = this.getUserInfoByToken(userToken);
            if (userInfoByToken != null) {
                return this.userIdThrough(exchange, chain, userInfoByToken);
            } else {
                //令牌不为null，但是查不到用户信息，就是假冒令牌，直接踢回首页
                return locationUrl(exchange, authResourceProperties.getMainUrl());
            }
        } else {
            //透传临时用户的id
            return this.userTempIdThrough(exchange, chain);
        }
    }

    private Mono<Void> userTempIdThrough(ServerWebExchange exchange, GatewayFilterChain chain) {
        String userTempId = this.getUserTempId(exchange);
        ServerHttpRequest httpRequest = exchange.getRequest().mutate().header("userTempId", userTempId).build();
        ServerWebExchange webExchange = exchange.mutate().request(httpRequest).response(exchange.getResponse()).build();
        return chain.filter(webExchange);
    }

    private String getUserTempId(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        HttpCookie cookie = request.getCookies().getFirst("userTempId");
        if (cookie != null) {
            return cookie.getValue();
        } else {
            String userTempId = request.getHeaders().getFirst("userTempId");
            return userTempId;
        }
    }

    private Mono<Void> userIdThrough(ServerWebExchange exchange, GatewayFilterChain chain, UserInfo userInfo) {
        String userTempId = this.getUserTempId(exchange);
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpRequest newRequest = request.
                mutate()
                .header("userId", userInfo.getId().toString())
                .header("userTempId",userTempId)
                .build();//透传id也把临时id进行透传方便后续购物车的合并

        ServerWebExchange newExchange = exchange//重新构建一个exchange
                .mutate()
                .request(newRequest)
                .response(exchange.getResponse())
                .build();
        return chain.filter(newExchange);
    }

    //踢回首页的方法
    private Mono<Void> locationUrl(ServerWebExchange exchange, String mainUrl) {
        String uri = exchange.getRequest().getURI().getPath().toString();
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.FOUND);
        response.getHeaders().set("location", mainUrl + uri);

//清除错误的cookie防止多次重定向；
        ResponseCookie responseCookie = ResponseCookie.from("token", "")
                .domain(".gmall.com")
                .maxAge(0)
                .build();
        ResponseCookie responseCookie2 = ResponseCookie.from("userInfo", "")
                .domain(".gmall.com")
                .maxAge(0)
                .build();
        response.addCookie(responseCookie);
        response.addCookie(responseCookie2);
        return response.setComplete();
    }

    private UserInfo getUserInfoByToken(String token) {
        String jsonString = redisTemplate.opsForValue().get(GmallCacheConstant.REDIS_USER_INFO + token);
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        } else {
            return JSON.parseObject(jsonString, UserInfo.class);
        }

    }

    private String getUserToken(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        String token = "";
        HttpCookie tokenCookie = request.getCookies().getFirst("token");
        if (tokenCookie != null) {
            token = tokenCookie.getValue();
        } else {
            token = request.getHeaders().getFirst("token");//从请求头种获取token
        }
        return token;
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
